package com.mapforge.collection;

import java.util.HashSet;
import java.util.List;
import java.util.NoSuchElementException;

/**
 * The {@link AbstractCache} is an abstract implementation of {@link Cache} in
 * that it handles the basic cache behavior but doesn't provide a framework for
 * the actual data structure implementation of the cache itself. This means the
 * final implementation of a {@link Cache} could implement a {@link HashSet} or
 * more simple data structure like a {@link List}.
 * 
 * @author Will Morrison
 * 
 * @param <T>
 */
public abstract class AbstractCache<T> implements Cache<T> {
	/**
	 * Factory providing new instances of the generic this cache provides.
	 */
	private Factory<T> factory;

	/**
	 * Constructs a new {@link AbstractCache} using the specified
	 * {@link Factory}.
	 * 
	 * @param factory
	 *            specified factory used to construct new instances
	 */
	public AbstractCache(Factory<T> factory) {
		this.factory = factory;
	}

	@Override
	public Factory<T> getFactory() {
		return factory;
	}

	@Override
	public void setFactory(Factory<T> factory) {
		this.factory = factory;
	}

	@Override
	public T getInstance() {
		if (isEmpty()) {
			return factory.createInstance();
		} else {
			return getCachedInstance();
		}
	}

	/**
	 * Retrieves a cached instance of the generic this cache caches. Throws a
	 * {@link NoSuchElementException} should there be no chache'd instances
	 * available.
	 * 
	 * @return cached instance of generic
	 * @throws NoSuchElementException
	 *             if there is no cached instance to retrieve
	 */
	protected abstract T getCachedInstance() throws NoSuchElementException;
}
